/***
 * @Description: 本文件是关于IP协议的相关配置的C语言文件，主要包括数据结构定义，IPv4协议封装实现，IP数据包的收发解析，数据包分片重组实现等功能
 * @Author: Liverpool
 * @Date: 2024-07-03 02:00:55
 * @LastEditTime: 2024-07-03 02:01:15
 * @LastEditors: Liverpool
 */

#include "ipv4.h"
#include "debug.h"
#include "tools.h"
#include "protocol.h"
#include "icmpv4.h"
#include "timer.h"
#include "raw.h"

// 变量定义区
// 常规变量定义区
static uint16_t packet_id = 0;
// 分片重组变量定义区
static D_IPv4_Fragment fragment_array[IPv4_FRAGMENT_MAX_SIZE]; // 分片重组结构体的数组
static D_MemoryBlock fragment_memory_block;                    // 分片链表的的内存管理系统
static D_List fragment_list;                                   // 分片链表
static D_Net_timer fragment_timer;                             // IPv4的分片定时器

#if Debug_Display_Enable(Debug_IPv4)

/***
 * @description: (静态函数)对IPv4协议报文进行展示
 * @Author: Liverpool
 * @Date: 2024-07-26 23:11:46
 * @return {*}
 * @param {D_IPv4_Packet} *packet 需要展示的数据报内存地址
 */
static void display_ipv4_packet(D_IPv4_Packet *packet)
{
    D_IPv4_Header *ipv4_header = &packet->header;
    plat_printf("---------------------IPv4 packet--------------------------\n");
    plat_printf("\tversion:%d\n", ipv4_header->version);
    plat_printf("\theader len:%d\n", ipv4_header_size(packet));
    plat_printf("\ttotal len:%d\n", ipv4_header->total_len);
    plat_printf("\tid:%d\n", ipv4_header->Id);
    plat_printf("\tfragment disable flag:%d\n", ipv4_header->disable_flag);
    plat_printf("\tfragment more flag:%d\n", ipv4_header->more_flag);
    plat_printf("\tfragment offset:%d\n", ipv4_header->offset);
    plat_printf("\tttl:%d\n", ipv4_header->ttl);
    plat_printf("\tprotocol:%d\n", ipv4_header->protocol);
    plat_printf("\tchecksum:%d\n", ipv4_header->header_checksum);
    debug_dump_ipaddr_buf("\tsrc ip:", ipv4_header->src_ip);
    debug_dump_ipaddr_buf("\n\tdest ip:", ipv4_header->dest_ip);
    plat_printf("\n---------------------IPv4 end--------------------------\n");
}

/***
 * @description: (静态函数)对IPv4协议的分片结构进行展示
 * @Author: Liverpool
 * @Date: 2024-07-26 23:24:24
 * @return {*}
 */
static void display_ip_fragments(void)
{
    plat_printf("---------------------IP fragments--------------------------\n");
    int f_index = 0;
    D_ListNode *frag_node;
    list_for_each_node(frag_node, &fragment_list)
    {
        D_IPv4_Fragment *fragment = list_entry(frag_node, D_IPv4_Fragment, node);
        plat_printf("[%d]\n", f_index++);
        debug_dump_ipaddr("\tip:", &fragment->ip);
        plat_printf("\n\tid: %d\n", fragment->id);
        plat_printf("\tms:%d\n", fragment->ms);
        plat_printf("\tbufs:%d\n", list_get_count(&fragment->buf_list));
        plat_printf("\tbufs:\n");
        D_ListNode *p_node;
        int p_index = 0;
        list_for_each_node(p_node, &fragment->buf_list)
        {
            D_Packet *buf = list_entry(p_node, D_Packet, node);
            D_IPv4_Packet *packet = (D_IPv4_Packet *)packet_firstBlock_data(buf);
            plat_printf("\tB%d:[%d-%d],  ", p_index++, get_fragment_start(packet), get_fragment_end(packet) - 1);
        }
        plat_printf("\n");
    }
    plat_printf("---------------------IP fragments end----------------------\n");
}
#else
#define display_ipv4_packet(packet)
#define display_ip_fragments()
#endif

/***
 * @description:(静态函数)对收到的IP数据包进行合法校验
 * @Author: Liverpool
 * @Date: 2024-07-09 16:49:49
 * @return {*} 返回是否合法，0: 代表数据包合法 <0: 表示数据包不合法
 * @param {D_IPv4_Packet} *packet 需要进行检测的IP数据包的内存地址
 * @param {int} total_size 整个IP数据包的大小
 * @param {D_Net_Interface} *netif 接收到的数据包的网卡内存地址
 */
static net_err_t is_IPv4_packet_ok(D_IPv4_Packet *packet, int total_size, D_Net_Interface *netif)
{
    // 对IPv4的数据包头进行合法校验
    // 1.对头部的IP协议进行判断
    if (packet->header.version != NET_VERSION_IPV4)
    {
        // 不支持除了IPv4协议以外的IP协议
        debug_Warning(Debug_IPv4, "don't support this version of IP...");
        return NET_ERR_NOT_SUPPORT;
    }
    // 2.对头部的数据长短进行判断
    int header_len = ipv4_header_size(packet);
    if (header_len < sizeof(D_IPv4_Header))
    {
        debug_Warning(Debug_IPv4, "ipv4 packet header size error...");
        return NET_ERR_SIZE;
    }
    // 3.对数据报整体的数据长度进行判断
    int total_len = x_ntohs(packet->header.total_len);
    if (total_len < sizeof(D_IPv4_Header) || total_len > total_size)
    {
        // 如果接收到的数据报的整体大小小于报头的大小或者比网卡收到的数据报大小还大，那就是不正常的
        debug_Warning(Debug_IPv4, "ipv4 packet total size error...");
        return NET_ERR_SIZE;
    }
    // 4.使用校验和对头部数据进行校验处理
    if (packet->header.header_checksum)
    {
        uint16_t value = checksum_16(0, packet, header_len, 0, 1); // 进行校验和计算，如果正确其值为0
        if (value != 0)
        {
            debug_Warning(Debug_IPv4, "ip packet header checksum error, check value =%d", value);
            return NET_ERR_BROKEN;
        }
    }

    return NET_ERR_OK;
}

/***
 * @description: IPv4协议的数据报头部数据进行转换(网络端——>本地端)
 * @Author: Liverpool
 * @Date: 2024-07-09 17:30:54
 * @return {*}
 * @param {D_IPv4_Packet} *packet 需要转换的IP数据报内存地址
 */
static void IPv4_header_xntohs(D_IPv4_Packet *packet)
{
    packet->header.total_len = x_ntohs(packet->header.total_len);
    packet->header.Id = x_ntohs(packet->header.Id);
    packet->header.fragment_all = x_ntohs(packet->header.fragment_all);
}

/***
 * @description: IPv4协议的数据报头部数据进行转换(本地端->网络端)
 * @Author: Liverpool
 * @Date: 2024-07-09 17:30:54
 * @return {*}
 * @param {D_IPv4_Packet} *packet 需要转换的IP数据报内存地址
 */
static void IPv4_header_xhtons(D_IPv4_Packet *packet)
{
    packet->header.total_len = x_htons(packet->header.total_len);
    packet->header.Id = x_htons(packet->header.Id);
    packet->header.fragment_all = x_htons(packet->header.fragment_all);
}

/***
 * @description: (静态函数)单个IP数据包的正常深度内部数据解析函数
 * @Author: Liverpool
 * @Date: 2024-07-10 12:33:35
 * @return {*} 在解析过程中出现的错误
 * @param {D_Net_Interface} *netif 接收数据报的网卡的内存地址
 * @param {D_Packet} *buf 接收到的数据报的内存地址
 * @param {D_IP_ADDR} *src_ip 源地址
 * @param {D_IP_ADDR} *dest_ip 目的地址
 */
static net_err_t ipv4_normal_in(D_Net_Interface *netif, D_Packet *buf, D_IP_ADDR *src_ip, D_IP_ADDR *dest_ip)
{
    D_IPv4_Packet *packet = (D_IPv4_Packet *)packet_firstBlock_data(buf);
    display_ipv4_packet(packet);
    // 根据不同的协议,转发给不同的上层协议处理
    switch (packet->header.protocol)
    {
    case Net_Protocol_ICMPv4:
        net_err_t err = icmpv4_in(src_ip, &netif->ipaddr, buf);
        if (err < 0)
        {
            debug_Warning(Debug_IPv4, "icmpv4 in failed, err=%d", err);
            return err;
        }
        return NET_ERR_OK;
        break;
    case Net_Protocol_UDP:
        IPv4_header_xhtons(packet);
        icmpv4_out_unreach(src_ip, &netif->ipaddr, ICMPv4_UNREACH_PORT, buf);
        break;
    case Net_Protocol_TCP:
        break;
    default:
        debug_Warning(Debug_IPv4, "don't support this protocol, =%d...", packet->header.protocol);
        err = raw_in(buf);
        if (err < 0)
        {
            debug_Warning(Debug_IPv4, "raw in error");
        }
        return NET_ERR_UNREACH;
        break;
    }
    return NET_ERR_UNREACH;
}

/***
 * @description: 对分片结构中的接收到的数据报进行释放
 * @Author: Liverpool
 * @Date: 2024-07-17 23:55:39
 * @return {*}
 * @param {D_IPv4_Fragment *} fragment 需要清除数据报的分片结构的内存地址
 */
static void fragment_free_buf_list(D_IPv4_Fragment *fragment)
{
    D_ListNode *node;
    while ((node = list_remove_first(&fragment->buf_list)))
    {
        D_Packet *buf = list_entry(node, D_Packet, node);
        packet_free(buf);
    }
}

/***
 * @description: 分片结构体的分配
 * @Author: Liverpool
 * @Date: 2024-07-17 23:43:58
 * @return {*} 返回分片结构体的内存地址
 */
static D_IPv4_Fragment *fragment_alloc(void)
{
    D_IPv4_Fragment *fragment = memory_block_alloc(&fragment_memory_block, -1); // 需要立即分配一个fragment
    if (!fragment)
    {
        D_ListNode *node = list_remove_last(&fragment_list); // 找到时间最长的分片
        fragment = list_entry(node, D_IPv4_Fragment, node);
        if (fragment)
        {
            fragment_free_buf_list(fragment);
        }
    }
    return fragment;
}

/***
 * @description: 对分片结构进行回收释放处理
 * @Author: Liverpool
 * @Date: 2024-07-18 00:04:42
 * @return {*}
 * @param {D_IPv4_Fragment} *fragment 需要回收释放的分片结构的内存地址
 */
static void fragment_free(D_IPv4_Fragment *fragment)
{
    fragment_free_buf_list(fragment);
    list_remove_node(&fragment_list, &fragment->node);
    memory_block_free(&fragment_memory_block, fragment);
}

/***
 * @description: （静态函数）在分片链表中插入一个新的分片结构数据
 * @Author: Liverpool
 * @Date: 2024-07-23 01:04:23
 * @return {*}
 * @param {D_IPv4_Fragment} *fragment 需要插入的分片结构内存地址
 * @param {D_IP_ADDR} ip 插入的IP地址
 * @param {uint16_t} id IP数据报的ID号
 */
static void fragment_add(D_IPv4_Fragment *fragment, D_IP_ADDR *ip, uint16_t id)
{
    ipaddr_copy(&fragment->ip, ip);
    fragment->ms = IPv4_FRAGMENT_MAX_MS / IPv4_FRAGMENT_SCAN_PERIOD;
    fragment->id = id;
    list_node_init(&fragment->node);
    list_init(&fragment->buf_list);
    list_insert_first(&fragment_list, &fragment->node); // 插入到链表的最前面
}

/***
 * @description: （静态函数）在分片结构链表中寻找对应的IP分片分组
 * @Author: Liverpool
 * @Date: 2024-07-23 00:49:49
 * @return {*} 找到的对应的IP分片分组的内存地址
 * @param {D_IP_ADDR} *ip 需要查找的IP地址
 * @param {uint16_t} id 需要查找的IP数据报中的ID
 */
static D_IPv4_Fragment *fragment_find(D_IP_ADDR *ip, uint16_t id)
{
    D_ListNode *curr;
    // 遍历整个分片结构链表
    list_for_each_node(curr, &fragment_list)
    {
        D_IPv4_Fragment *fragment = list_entry(curr, D_IPv4_Fragment, node);
        // 只有当源IP地址相同并且发送的ID号也相同时，才能确定找到对应的IP分片结构
        if (ipaddr_is_equal(ip, &fragment->ip) && (id == fragment->id))
        {
            // 把找到fragment分片结构放在整个链表的最前面
            list_remove_node(&fragment_list, curr);
            list_insert_first(&fragment_list, curr);
            return fragment;
        }
    }
    return (D_IPv4_Fragment *)0;
}

/***
 * @description: (静态函数)在IP分片结构中插入数据包
 * @Author: Liverpool
 * @Date: 2024-07-27 00:41:10
 * @return {*} 插入过程中出现的错误
 * @param {D_IPv4_Fragment} *fragment需要插入的分片结构地址
 * @param {D_Packet} *buf 需要插入的数据包内存地址
 * @param {D_IPv4_Packet} *packet 需要插入的数据解析报文
 */
static net_err_t fragment_insert_buf(D_IPv4_Fragment *fragment, D_Packet *buf, D_IPv4_Packet *packet)
{
    // 对分片结构的存储的数据包要进行数量检测
    if (list_get_count(&fragment->buf_list) >= IPv4_FRAGMENT_MAX_BUF_SIZE)
    {
        debug_Warning(Debug_IPv4, "too many bufs on fragment");
        fragment_free(fragment);
        return NET_ERR_FULL;
    }
    // 进行数据报的加入
    D_ListNode *node;
    list_for_each_node(node, &fragment->buf_list)
    {
        D_Packet *curr_buf = list_entry(node, D_Packet, node);
        D_IPv4_Packet *curr_packet = (D_IPv4_Packet *)packet_firstBlock_data(curr_buf);
        uint16_t curr_start = get_fragment_start(curr_packet);
        if (get_fragment_start(packet) == curr_start) // 表示这两个包重复出现，需要丢弃
        {
            return NET_ERR_EXIST;
        }
        else if (get_fragment_start(packet) <= curr_start) // 说明现在的数据报在当前的数据包前面
        {
            D_ListNode *pre = list_node_get_pre(node); // 得到当前节点的前一个节点
            if (pre)                                   // 就插入在当前节点的前节点的后面
            {
                list_insert_after(&fragment_list, pre, &buf->node);
            }
            else // 如果前节点没有存在，那就插入在队头节点
            {
                list_insert_first(&fragment->buf_list, &buf->node);
            }
            return NET_ERR_OK;
        }
    }
    list_insert_last(&fragment->buf_list, &buf->node); // 如果还没有插入，那就直接插入在队尾处
    return NET_ERR_OK;
}
/***
 * @description: (静态函数)IPv4分片结构的扫描函数
 * @Author: Liverpool
 * @Date: 2024-08-06 00:10:58
 * @return {*}
 * @param {D_Net_timer} *timer 传入的定时器的内存地址
 * @param {void} *arg 形参
 */
static void fragment_timer_ms(D_Net_timer *timer, void *arg)
{
    D_ListNode *curr, *next;
    for (curr = list_get_first(&fragment_list); curr; curr = next)
    {
        next = list_node_get_next(curr);
        D_IPv4_Fragment *fragment = list_entry(curr, D_IPv4_Fragment, node);
        if (--fragment->ms <= 0) // 到达时间后，就对分片结构进行释放
        {
            fragment_free(fragment);
        }
    }
}

/***
 * @description: 对分片重组功能进行初始化
 * @Author: Liverpool
 * @Date: 2024-07-17 22:31:04
 * @return {*} 返回初始化过程中出现的错误
 */
static net_err_t fragment_init(void)
{
    list_init(&fragment_list);
    net_err_t err = memory_block_init(&fragment_memory_block, fragment_array, sizeof(D_IPv4_Fragment), IPv4_FRAGMENT_MAX_SIZE, Locker_Self);
    err = net_timer_add(&fragment_timer, "fragment timer", fragment_timer_ms, (void *)0, IPv4_FRAGMENT_SCAN_PERIOD * 1000, NET_TIMER_RELOAD);
    if (err < 0)
    {
        debug_error(Debug_IPv4, "create fragment timer failed...");
    }
    return err;
}

/***
 * @description: (静态函数)检查分片结构中的数据包列表是否全部到达
 * @Author: Liverpool
 * @Date: 2024-07-31 23:55:59
 * @return {*} 是否全部到达 1:表示全部到达 0:表示没有全部达到
 * @param {D_IPv4_Fragment} *fragment 需要检查的分片结构的内存地址
 */
static int fragment_is_all_arrived(D_IPv4_Fragment *fragment)
{
    int offset = 0;
    D_ListNode *node;
    D_IPv4_Packet *packet = (D_IPv4_Packet *)0;
    list_for_each_node(node, &fragment->buf_list)
    {
        D_Packet *buf = list_entry(node, D_Packet, node);
        packet = (D_IPv4_Packet *)packet_firstBlock_data(buf);
        int curr_offset = get_fragment_start(packet); // 得到当前数据报的偏离位置
        if (curr_offset != offset)                    // 如果当前偏离没有等于数据包的遍历，那就说明数据包没有全部到达
        {
            return 0;
        }
        offset += curr_offset + get_ipv4_data_size(packet);
    }
    return packet ? !packet->header.more_flag : 0; // 最后需要查看more_flag有没有归零；0：就代表数据包全部到达
}

/***
 * @description: (静态函数)把分片结构里面的数据包进行合并重组在一起
 * @Author: Liverpool
 * @Date: 2024-08-01 00:20:05
 * @return {*} 返回合并后的数据包内存地址
 * @param {D_IPv4_Fragment} *fragment 需要合并的分片结构的内存地址
 */
static D_Packet *fragment_join(D_IPv4_Fragment *fragment)
{
    D_Packet *target = (D_Packet *)0;
    D_ListNode *node;
    while ((node = list_remove_first(&fragment->buf_list)))
    {
        D_Packet *curr = list_entry(node, D_Packet, node);
        if (!target) // 使target的目标地址为第一个数据包的内存地址
        {
            target = curr;
            continue;
        }
        // 进行数据包合并
        D_IPv4_Packet *packet = (D_IPv4_Packet *)packet_firstBlock_data(curr);
        net_err_t err = packet_remove_header(curr, ipv4_header_size(packet)); // 移除包头操作
        if (err < 0)
        {
            debug_error(Debug_IPv4, "remove header failed...");
            packet_free(curr);
            goto free_and_return;
        }
        err = packet_join(target, curr);
        if (err < 0)
        {
            debug_error(Debug_IPv4, "join ip fragment failed...");
            packet_free(curr);
            goto free_and_return;
        }
    }
    fragment_free(fragment); // 合并完成后，直接释放分片结构
    return target;
free_and_return:
    if (target)
    {
        packet_free(target);
    }
    fragment_free(fragment);
    return (D_Packet *)0;
}

/***
 * @description: (静态函数)对IPv4协议下的分片重组，多个IP数据报合并成一个较大的数据报
 * @Author: Liverpool
 * @Date: 2024-07-10 12:33:35
 * @return {*} 在解析过程中出现的错误
 * @param {D_Net_Interface} *netif 接收数据报的网卡的内存地址
 * @param {D_Packet} *buf 接收到的数据报的内存地址
 * @param {D_IP_ADDR} *src_ip 源地址
 * @param {D_IP_ADDR} *dest_ip 目的地址
 */
static net_err_t ipv4_fragment_in(D_Net_Interface *netif, D_Packet *buf, D_IP_ADDR *src_ip, D_IP_ADDR *dest_ip)
{
    D_IPv4_Packet *packet = (D_IPv4_Packet *)packet_firstBlock_data(buf);
    D_IPv4_Fragment *fragment = fragment_find(src_ip, packet->header.Id); // 查找对应的分片结构
    if (!fragment)
    {
        fragment = fragment_alloc();                       // 分配对应的分配结构
        fragment_add(fragment, src_ip, packet->header.Id); // 在分片结构链表中插入新的分片
    }
    net_err_t err = fragment_insert_buf(fragment, buf, packet);
    if (err < 0)
    {
        debug_Warning(Debug_IPv4, "fragment insert buf failed.");
        return err;
    }
    display_ip_fragments();                // 对分片结构进行打印
    if (fragment_is_all_arrived(fragment)) // 如果所有数据包分片全部到达，需要进行数据包合并
    {
        D_Packet *full_buf = fragment_join(fragment);
        if (!full_buf) // 合并失败
        {
            debug_error(Debug_IPv4, "join ip bufs failed...");
            display_ip_fragments(); // 对分片结构进行打印
            return NET_ERR_OK;
        }

        err = ipv4_normal_in(netif, full_buf, src_ip, dest_ip); // 进行ipv4的常规处理
        if (err < 0)
        {
            debug_Warning(Debug_IPv4, "ip fragment in failed, error: %d", err);
            packet_free(full_buf);
            return NET_ERR_OK;
        }
    }
    return NET_ERR_OK;
}

/***
 * @description: IPv4协议的初始化函数
 * @Author: Liverpool
 * @Date: 2024-07-03 02:03:23
 * @return {*} 在初始化过程中出现的错误
 */
net_err_t ipv4_init(void)
{
    debug_info(Debug_IPv4, "IPv4 init...");
    net_err_t err = fragment_init();
    if (err < 0)
    {
        debug_error(Debug_IPv4, "IPv4 fragment init failed, err = %d...", err);
        return err;
    }
    debug_info(Debug_IPv4, "IPv4 init done...");
    return NET_ERR_OK;
}

/***
 * @description: 对数据包做IP协议的输入解析处理
 * @Author: Liverpool
 * @Date: 2024-07-08 12:39:54
 * @return {*} 解析过程中出现的错误
 * @param {D_Net_Interface} *netif 网卡的内存地址
 * @param {D_Packet} *buf 需要进行解析处理的数据包内存地址
 */
net_err_t ipv4_in(D_Net_Interface *netif, D_Packet *buf)
{
    debug_info(Debug_IPv4, "IPv4 in...");
    net_err_t err = packet_set_continuous(buf, sizeof(D_IPv4_Header)); // 把IPv4协议的帧头设置为连续模式
    if (err < 0)
    {
        debug_error(Debug_IPv4, "adjust header failed,err = %d", err);
        return err;
    }
    D_IPv4_Packet *packet = (D_IPv4_Packet *)packet_firstBlock_data(buf);
    if ((err = is_IPv4_packet_ok(packet, buf->total_size, netif)) != NET_ERR_OK)
    {
        debug_Warning(Debug_IPv4, "packet is broken...");
        return err;
    }
    IPv4_header_xntohs(packet);                         // 进行数据包头部数据的转化
    err = packet_resize(buf, packet->header.total_len); // 根据IP数据报的总长度对数据包进行重切割
    if (err < 0)
    {
        debug_error(Debug_IPv4, "ip packet resize failed,err = %d", err);
        return err;
    }
    // 获取IP地址
    D_IP_ADDR dest_ip, src_ip;
    ipaddr_from_buf(&dest_ip, packet->header.dest_ip);
    ipaddr_from_buf(&src_ip, packet->header.src_ip);
    // 对于接收到的IP地址需要和网卡的为同一个子网下,才能保证数据报是可以接收的
    if (!ipaddr_is_match(&dest_ip, &netif->ipaddr, &netif->netmask))
    {
        debug_Warning(Debug_IPv4, "ip packet not match...");
        return NET_ERR_UNREACH;
    }

    if (packet->header.offset || packet->header.more_flag)
    {
        err = ipv4_fragment_in(netif, buf, &src_ip, &dest_ip); // 分片重组处理
    }
    else
    {
        err = ipv4_normal_in(netif, buf, &src_ip, &dest_ip); // 对IPv4数据报做内部的数据解析
    }
    return err;
}

/***
 * @description: IPv4协议分片向外部传输数据(IPv4数据包过大)
 * @Author: Liverpool
 * @Date: 2024-08-04 22:32:55
 * @return {*} 发送过程中出现的错误
 * @param {uint8_t} protocol 协议
 * @param {D_IP_ADDR} *dest 目的IP地址
 * @param {D_IP_ADDR} *src 源IP地址
 * @param {D_Packet} *buf 需要发送的数据包
 * @param {D_Net_Interface} *netif 发送的网卡
 */
static net_err_t ipv4_fragment_out(uint8_t protocol, D_IP_ADDR *dest, D_IP_ADDR *src, D_Packet *buf, D_Net_Interface *netif)
{
    debug_info(Debug_IPv4, "ipv4 fragment send ip packet");
    packet_reset_access(buf); // 重定位数据包的数据指针
    int offset = 0;
    int total = buf->total_size;
    while (total)
    {
        int current_size = total;
        if (current_size > (netif->mtu - sizeof(D_IPv4_Header)))
        {
            current_size = netif->mtu - sizeof(D_IPv4_Header);
        }
        // 分配一个存储空间，用来对发送的数据进行分片存储复制和发送
        D_Packet *dest_buf = packet_alloc(current_size + sizeof(D_IPv4_Header));
        if (!dest_buf)
        {
            debug_error(Debug_IPv4, "ipv4 alloc buffer for fragment send failed...");
            return NET_ERR_NONE;
        }
        // 进行IPv4数据包头的增加
        D_IPv4_Packet *packet = (D_IPv4_Packet *)packet_firstBlock_data(dest_buf);
        packet->header.shotheader_all = 0;
        packet->header.version = NET_VERSION_IPV4;
        ipv4_set_header_size(packet, sizeof(D_IPv4_Header));
        packet->header.total_len = dest_buf->total_size;
        packet->header.Id = packet_id;
        packet->header.fragment_all = 0; // 先不考虑分组且片的情况
        packet->header.ttl = NET_IP_DEFAULT_TTL;
        packet->header.protocol = protocol;
        packet->header.header_checksum = 0;
        ipaddr_to_buf(src, packet->header.src_ip);
        ipaddr_to_buf(dest, packet->header.dest_ip);
        // 进行IPv4分组情况
        packet->header.offset = offset >> 3;             // 进行一个/8操作
        packet->header.disable_flag = 1;                 // 进行分片
        packet->header.more_flag = total > current_size; // 进行一个分片more_flag的赋值
        // 进行数据包内容的copy
        packet_seek(dest_buf, sizeof(D_IPv4_Header));             // 定位copy位置
        net_err_t err = packet_copy(dest_buf, buf, current_size); // 进行数据包copy
        if (err < 0)
        {
            debug_error(Debug_IPv4, "fragment copy failed...");
            packet_free(dest_buf);
            return err;
        }
        // 对原数据包已经copy的部分可以释放
        packet_remove_header(buf, current_size);
        packet_reset_access(buf);

        IPv4_header_xhtons(packet); // 进行大小端的转化
        packet_reset_access(dest_buf);
        packet->header.header_checksum = packet_checksum_16(dest_buf, ipv4_header_size(packet), 0, 1);
        display_ipv4_packet(packet);

        err = net_interface_out(netif, dest, dest_buf);
        if (err < 0)
        {
            debug_Warning(Debug_IPv4, "send ip packet faile, error=%d", err);
            packet_free(dest_buf);
            return err;
        }
        offset += current_size;
        total -= current_size;
    }
    packet_id++;
    packet_free(buf);
    return NET_ERR_OK;
}

/***
 * @description: IPv4协议通过目的IP地址向外发送数据报
 * @Author: Liverpool
 * @Date: 2024-07-10 15:42:55
 * @return {*} 发送过程中出现的错误
 * @param {int} protocol 协议
 * @param {D_IP_ADDR} *dest 目的地址
 * @param {D_IP_ADDR} *src 源地址
 * @param {D_Packet} *buf 发送的数据报的内存地址
 */
net_err_t ipv4_out(uint8_t protocol, D_IP_ADDR *dest, D_IP_ADDR *src, D_Packet *buf)
{
    debug_info(Debug_IPv4, "send an ipv4 packet...");
    D_Net_Interface *netif = net_interface_get_default();                     // 得到默认网卡地址
    if (netif->mtu && (buf->total_size + sizeof(D_IPv4_Header)) > netif->mtu) // 如果IPv4的数据包太大，那就需要进行分片发送
    {
        net_err_t err = ipv4_fragment_out(protocol, dest, src, buf, netif);
        if (err < 0)
        {
            debug_Warning(Debug_IPv4, "send ipv4 fragment failed...");
            return err;
        }
        return NET_ERR_OK;
    }

    net_err_t err = packet_add_header(buf, sizeof(D_IPv4_Header), Packet_Header_Continuous); // 在需要发送的数据报前面添加连续的包头
    if (err < 0)
    {
        debug_error(Debug_IPv4, "add ip header failed, err = %d", err);
        return NET_ERR_SIZE;
    }
    // 对IP数据报的头部信息进行设置
    D_IPv4_Packet *packet = (D_IPv4_Packet *)packet_firstBlock_data(buf);
    packet->header.shotheader_all = 0;
    packet->header.version = NET_VERSION_IPV4;
    ipv4_set_header_size(packet, sizeof(D_IPv4_Header));
    packet->header.total_len = buf->total_size;
    packet->header.Id = packet_id++;
    packet->header.fragment_all = 0; // 先不考虑分组且片的情况
    packet->header.ttl = NET_IP_DEFAULT_TTL;
    packet->header.protocol = protocol;
    packet->header.header_checksum = 0;
    ipaddr_to_buf(src, packet->header.src_ip);
    ipaddr_to_buf(dest, packet->header.dest_ip);
    IPv4_header_xhtons(packet); // 进行大小端的转化
    packet_reset_access(buf);
    packet->header.header_checksum = packet_checksum_16(buf, ipv4_header_size(packet), 0, 1);
    display_ipv4_packet(packet);

    err = net_interface_out(net_interface_get_default(), dest, buf);
    if (err < 0)
    {
        debug_Warning(Debug_IPv4, "send ip packet faile, error=%d", err);
        return err;
    }

    return NET_ERR_OK;
}